/**
 * 
 */
package cs342.project1.mathNotebook.PKI;

import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;

/** Represents a public key component of the RSA asymmetric encryption scheme.
 * @author Aaron Heise
 *
 */
public class SimpleRSAPublicKey extends SimpleRSAKey implements RSAPublicKey {

	/**
	 * 
	 */
	private static final long serialVersionUID = 10939837509873L;
	
	protected RSAPublicKey publicKey = null;
	
	/** Wraps an <a href="http://download.oracle.com/javase/1.4.2/docs/api/java/security/interfaces/RSAPublicKey.html">RSAPublicKey</a>.
	 * @param publicKey Public Key to wrap
	 */
	public SimpleRSAPublicKey(RSAPublicKey publicKey) {
		super();
		this.publicKey = publicKey;
	}
	
	/**  Creates a public key from an array of bytes
	 * @param encodedKey the encoded key
	 * @return the key object
	 * @throws SimpleRSAAlgorithmException Problem with the RSA implementation used by the JVM
	 * @throws SimpleRSAKeySpecException Problem with the encoded key
	 */
	protected static RSAPublicKey loadPublicKey(byte[] encodedKey) throws  SimpleRSAAlgorithmException, SimpleRSAKeySpecException {
		X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encodedKey);
		try {
			return (RSAPublicKey) getKeyFactory().generatePublic(pubKeySpec);
		} catch (InvalidKeySpecException e) {
			throw new SimpleRSAKeySpecException("Could not create key.", e);
		}
	}
	
	/** Creates a new key from a serialized representation
	 * @param encodedKey serialized representation of a public key
	 */
	public SimpleRSAPublicKey(byte[] encodedKey) throws SimpleRSAAlgorithmException, SimpleRSAKeySpecException {
		this(loadPublicKey(encodedKey));
	}
	
	/* (non-Javadoc)
	 * @see java.security.interfaces.RSAPublicKey#getPublicExponent()
	 */
	@Override
	public BigInteger getPublicExponent() {
		// TODO Auto-generated method stub
		return this.publicKey.getPublicExponent();
	}

	@Override
	protected Key getKey() {
		// TODO Auto-generated method stub
		return publicKey;
	}
	
	/** Encrypts clearData with this key
	 * @param clearData
	 * @return Returns the the bytes resulting from encrypting clearData with this key
	 * @throws SimpleRSAInvalidKeyException Problem with the key
	 * @throws SimpleRSADecryptionException Problem with the data
	 */
	public byte[] encrypt(byte[] clearData) throws SimpleRSAInvalidKeyException {
		try {
			rsa.init(Cipher.ENCRYPT_MODE, this.publicKey);
		} catch (InvalidKeyException e) {
			throw new SimpleRSAInvalidKeyException("There is a problem with the key.", e);
		}
		
		try {
			return rsa.doFinal(clearData);
		} catch (IllegalBlockSizeException e) {
			throw new SimpleRSAEncryptionException("Error encrypting data.", e);
		} catch (BadPaddingException e) {
			throw new SimpleRSAEncryptionException("Error encrypting data.", e);
		}
	}

}
